package com.spring.nio.core.http;

import com.spring.nio.common.BasicConstant;
import com.spring.nio.core.context.NioServerContext;
import com.spring.nio.core.http.model.RequestData;
import com.spring.nio.core.service.common.FileService;
import com.spring.nio.util.HttpUtil;
import com.spring.nio.util.LocalTime;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.time.LocalDateTime;

/**
 * @author: YSFY
 * @date: 2021-02-21 10:13
 * @pacage_name: com.spring.nio.core.http
 * @class_name: HttpRunnable
 * @description: http请求处理线程
 */

@Slf4j
public class HttpRunnable implements Runnable {
    private SocketChannel socketChannel;
    private HttpRequest httpRequest;
    private HttpResponse httpResponse;

    public HttpRunnable(SocketChannel socketChannel) {
        this.socketChannel = socketChannel;
    }

    @Override
    public void run() {
        try {
            if(!this.socketChannel.isOpen()) {
                log.info("[" + Thread.currentThread().getName() + " ] HttpRunnable | --> 文件http客户端服连接通道未打开处理失败,将关闭连接, 客户端地址 = [{}], thread = [{}]", NioServerContext.getRemoteAddress(socketChannel), Thread.currentThread().getName());
                return;
            }
            
            this.requestHandler();
        } catch (IOException e) {
            log.error("[" + LocalTime.formatDate(LocalDateTime.now()) + "] HttpRunnable | --> 处理文件Http客户端请求异常, 客户端地址 = [{}], error = [{}]", NioServerContext.getRemoteAddress(socketChannel), e.getMessage());
            e.printStackTrace();
        } finally {
            NioServerContext.closedAndRelease(this.socketChannel);
        }
    }

    private void requestHandler() throws IOException {
        RequestData requestData = this.parseHttp(this.readData());
        if(null == requestData) {
            NioServerContext.sendMessage(this.socketChannel, this.httpResponse);
            return;
        }

        this.handler(requestData);
    }

    /**
     * 读取http请求数据
     * @return
     * */
    private StringBuffer readData() throws IOException {
        int readBytes = 0;
        StringBuffer requestData = new StringBuffer("");
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(4096);
        while((readBytes = this.socketChannel.read(byteBuffer)) > 0) {
            byteBuffer.flip();
            byte[] bytes = new byte[readBytes];
            while(byteBuffer.hasRemaining()) {
                byteBuffer.get(bytes, 0, bytes.length);
                requestData.append(new String(bytes, 0, bytes.length));
            }
            byteBuffer.clear();
        }
        return requestData;
    }

    /**
     * 解析http请求
     * @param request
     * @return requestData(解析请求内的body数据)
     * */
    private RequestData parseHttp(StringBuffer request) {
        return HttpUtil.parseHttpRequest(request, this.httpRequest = HttpRequest.getInstance(), this.httpResponse = HttpResponse.getInstance());
    }

    /**
     * 执行业务处理
     * @param requestData
     * */
    private void handler(RequestData requestData) {
        if(StringUtils.isEmpty(requestData.getExec())) {
            HttpContext.ResponseData responseData = this.httpResponse.new ResponseData();
            responseData.setCode("101");
            responseData.setMessage("请求参数 [exec] 不能为空");
            return;
        }

        if(StringUtils.isEmpty(requestData.getData())) {
            HttpContext.ResponseData responseData = this.httpResponse.new ResponseData();
            responseData.setCode("101");
            responseData.setMessage("请求参数 [data] 不能为空");
            return;
        }

        // 上传
        if(StringUtils.equals(BasicConstant.UPLOAD, requestData.getExec())) {
            FileService.getFileService().uploadHandler(requestData, this.socketChannel);
        }

        // 下载
        if(StringUtils.equals(BasicConstant.DOWNLOAD, requestData.getExec())) {
            FileService.getFileService().downloadHandler(requestData);
        }
    }

}
